package com.fingard.dsp.bank.directbank.abc21;

import com.fingard.client.DspClient;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.abc02.util.RsaHelper;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.helpers.FileType;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.net.FtpPortClient;
import com.fingard.net.FtpReceiver;
import com.fingard.net.TcpReceiver;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;
import com.xwbank.sdk.base64.BASE64Encoder;

import java.io.File;
import java.security.PublicKey;

public class ABC21BatPayRec extends ABC21Base implements IBatPayRec {
    @Override
    public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_req1988.reqHeader);
        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req1988.ownAct, "");
            if (actItem == null) {
                retAts.respCode = "-1";
                retAts.respInfo = "未找到账号[" + p_req1988.ownAct + "]商户配置信息";
                retAts.writeRetToATS();
                return retAts;
            }
            String BusCode = StringHelper.isNullOrEmpty(actItem.busCode) ? "110" : actItem.busCode.toString();

            XmlTextWriter xmlWriter = new XmlTextWriter();
            ABC21Header bankHeader = new ABC21Header();
            bankHeader.transCode = "C602";
            bankHeader.reqSeqID = p_req1988.reqBatchNO;
            writeCommonHeader(xmlWriter, bankHeader);
            xmlWriter.writeElementString("SHAppCode", "SH04");
            xmlWriter.writeElementString("FileFlag", "1");
            xmlWriter.writeStartElement("Cmp");
            xmlWriter.writeElementClosed("BatchFileName");
            xmlWriter.writeEndElement();
            xmlWriter.writeEndDocument();

            StringBuilder tmpSbData = new StringBuilder();
            /** 第一行：汇总数据（记录长度500） */
            // 发起行号
            tmpSbData.append("0099999");
            // 代理业务种类
            tmpSbData.append(BusCode);
            // 代理业务序号
            tmpSbData.append("0000");
            // 明细序号
            tmpSbData.append("000000");
            // 记账状态
            tmpSbData.append("0");
            // 资料检查状态
            tmpSbData.append("0");
            // 总金额
            tmpSbData.append(String.format("%013d", Long.parseLong(StringHelper.amountMultiply100(p_req1988.totalAmt))));
            // 总笔数
            tmpSbData.append(String.format("%06d", Integer.parseInt(p_req1988.totalNum)));
            // 成功记账总金额
            tmpSbData.append("0000000000000");
            // 成功记账总笔数
            tmpSbData.append("000000");
            // 代理单位名称
            String recName = fixedLenCompleSpace(40, p_req1988.ownActName, false);
            tmpSbData.append(recName);
            // 代理单位账号
            String payAct = fixedLenCompleSpace(20, p_req1988.ownAct, false);
            tmpSbData.append(payAct);
            // 申请入账日期
            tmpSbData.append(Format.Date8Format.format(p_req1988.getPayDateOnly()));
            // 上传日期
            tmpSbData.append(Format.Date8Format.format(p_req1988.getPayDateOnly()));
            // 剩余天数
            tmpSbData.append("000");
            // 企业代码
            tmpSbData.append(fixedLenCompleSpace(18, bankFront.org, false));
            // 业务类型
            tmpSbData.append(fixedLenCompleSpace(3, "", false));
            // 预留信息
            tmpSbData.append(fixedLenCompleSpace(340, "", false));
            tmpSbData.append("\r\n");

            /** 第二行及以下：明细数据（记录长度500） */
            // 发起行号
            StringBuilder tmpSbSeqIDData = new StringBuilder();
            int i = 0;
            while (p_req1988.readRecord()) {
                i++;
                tmpSbData.append("0099999");
                // 代理业务种类
                tmpSbData.append(BusCode);
                // 代理业务序号
                tmpSbData.append("0000");
                // 明细序号
                tmpSbData.append(String.format("%06d", i));
                // 记账状态
                tmpSbData.append("0");
                // 收款方户名
                tmpSbData.append(fixedLenCompleSpace(40, p_req1988.readedDetail.recName, false));
                // 收款方账号
                String recAct = p_req1988.readedDetail.recAct;
                if (recAct.length() > 19) {
                    recAct = recAct.substring(0, 19);
                }
                recAct = fixedLenCompleSpace(19, recAct, false);
                tmpSbData.append(recAct);
                // 借贷标志
                tmpSbData.append("1");
                // 金额
                tmpSbData.append(String.format("%013d", Long.parseLong(StringHelper.amountMultiply100(p_req1988.readedDetail.payAmount))));
                // 币种
                String cur = convertCurToBank(p_req1988.readedDetail.payCur);
                tmpSbData.append(fixedLenCompleSpace(3, cur, false));
                // 传票号
                tmpSbData.append(fixedLenCompleSpace(8, "", false));
                // 记账错误码
                tmpSbData.append(fixedLenCompleSpace(4, "", false));
                // 记账日期
                tmpSbData.append("00000000");
                // 主机流水号
                tmpSbData.append("000000000");
                // 开户行
                tmpSbData.append("0000000");
                // 证件类型
                String certType = convertCertTypeToBank(p_req1988.readedDetail.certType);
                tmpSbData.append(fixedLenCompleSpace(6, certType, false));
                // 证件号码
                tmpSbData.append(fixedLenCompleSpace(40, p_req1988.readedDetail.certNum, false));
                // 摘要
                tmpSbData.append("00000000");
                // 备用
                tmpSbData.append(fixedLenCompleSpace(246, p_req1988.readedDetail.askNumber, false));
                // 二级账簿编号
                tmpSbData.append(fixedLenCompleSpace(10, "", false));
                // 备用
                tmpSbData.append(fixedLenCompleSpace(580, "", false));
                tmpSbData.append("\r\n");

                if (tmpSbSeqIDData.length() > 0) {
                    tmpSbSeqIDData.append("\r\n");
                }
                tmpSbSeqIDData.append(p_req1988.readedDetail.askNumber);
            }
            String tmpLocalMarkPath = getTempFileDirectory() + File.separator + p_req1988.reqBatchNO + ".txt";
            WriteBankLogLn2("批次明细序号映射文件路径: " + tmpLocalMarkPath);
            FileHelper.writeFile(tmpLocalMarkPath, tmpSbSeqIDData);
            String tmpFilePath = "";
            String tmpDataFileName = "C602_" + p_req1988.reqBatchNO + ".txt";
            if (StringHelper.isNullOrEmpty(bankFront.bkRecFolder)) {
                bankFront.bkRecFolder = bankFront.bkPayFolder;
            }
            tmpFilePath = StringHelper.trimEnd(bankFront.bkRecFolder, File.separator) + File.separator + tmpDataFileName;

            String cipherData = "";
            if ("dspfileserver".equals(this.bankFront.getAccessBkFileModeLowerCase())) {
                WriteBankLogLn("accessBkFileMode：" + bankFront.accessBkFileMode);
                DspClient dspClient = new DspClient(bankFront.dspFileServer);
                dspClient.charsetName = getCharset();
                TcpReceiver retReceiver = dspClient.putFile(isNeedHiddleField ? cipherData : tmpSbData.toString(), FileType.bankFile, tmpFilePath, false);
                if (retReceiver.isCompleted) {
                    String retXml = new String(retReceiver.recBytes, retReceiver.contentStartIndex, retReceiver.contentLength, retReceiver.charsetName);
                    XmlTextReader retXmlRd = new XmlTextReader(retXml);
                    if ("0".equals(retXmlRd.getSimpleText("RespCode"))) {
                        WriteBankLogLn("文件保存至前置机" + tmpFilePath + "成功");
                    } else {
                        WriteBankLogLn("文件保存至前置机" + tmpFilePath + "失败，响应报文：" + retXml);
                    }
                } else {
                    WriteBankLogLn("文件" + tmpFilePath + "保存失败：" + retReceiver.getConnMsg());
                    if (retReceiver.connState.equals(ConnState.FAIL)) {
                        WriteBankLogLn("连接主DSP服务" + bankFront.dspFileServer + "失败");
                    }
                }
            } else {
                WriteBankLogLn("请求代收付文件内容为:" + tmpSbData.toString());
                WriteBankLogLn("文件传送地址为:" + tmpFilePath);
                if (isNeedHiddleField) {

                    String bankPubKeyPath = getBankConfig().getValueAsString("BankPubKeyPath");
                    PublicKey publicKey = RsaHelper.decodePublicKeyFromFile(bankPubKeyPath);
                    // 对文件内容进行加密
                    byte[] encryptedDate = RsaHelper.encryptData(tmpSbData.toString().getBytes("gbk"), publicKey);
                    cipherData = new BASE64Encoder().encode(encryptedDate);
                    FileHelper.writeFile(tmpFilePath, cipherData, getCharset());
                } else {
                    FileHelper.writeFile(tmpFilePath, tmpSbData.toString(), getCharset());
                }
            }

            xmlWriter.writeEndDocument();// 写入报文完成
            String p_str = xmlWriter.toXmlString();
            p_str = p_str.replaceAll("<BatchFileName></BatchFileName>", "<BatchFileName>" + tmpDataFileName + "</BatchFileName>");
            String[] tmpStrRet = sendToBank(p_str);// 发送银行
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                // 解析银行返回
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRespCode = tmpBkReader.getFirstText("/ap/RespCode");
                    String tmpRetInfo = tmpBkReader.getFirstText("/ap/RespInfo");
                    String tmpRetRxtInfo = tmpBkReader.getFirstText("/ap/RxtInfo");
                    String tmpRespSource = tmpBkReader.getFirstText("/ap/RespSource");

                    // 当RxtInfo有内容返回，交易就会有异常
                    if (StringHelper.hasAnyChar(tmpRetRxtInfo)) {
                        retAts.respCode = "-1";
                        retAts.respInfo = tmpRetRxtInfo;
                    } else {
                        retAts.respCode = "0";
                        retAts.reqSeqID = p_req1988.reqBatchNO;
                        retAts.transState = tmpRespSource + "+" + tmpRespCode;
                        retAts.payInfoCode = tmpRespCode;
                        if ("0+0000".equals(retAts.transState)) {
                            retAts.respInfo = "提交处理成功，结果待查询！";
                        } else {
                            retAts.respInfo = tmpRetInfo;
                        }
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpSbMsg.toString();
                }
            } else if (tmpStrRet[0].equals(ConnState.FAIL)) {
                retAts.respCode = "0";
                retAts.respInfo = tmpStrRet[1];
                retAts.reqSeqID = p_req1988.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = tmpStrRet[0];
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = tmpStrRet[1];
            }

        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = e.toString();
            WriteBankLogLn(e);
        }
        if (retAts.respCode.equals("-1") && StringHelper.isNullOrEmpty(retAts.reqSeqID)) {
            retAts.reqSeqID = p_req1988.reqBatchNO;
        }
        retAts.writeRetToATS();
        return retAts;
    }

    @Override
    public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {

        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_req1998.reqHeader);
        retAts.reqSeqID = p_req1998.reqBatchNO;
        try {
            XmlTextWriter xmlWriter = new XmlTextWriter();
            ABC21Header bankHeader = new ABC21Header();
            bankHeader.transCode = "C602";
            bankHeader.reqSeqID = p_req1998.reqBatchNO;
            writeCommonHeader(xmlWriter, bankHeader);
            xmlWriter.writeElementString("SHAppCode", "SH05");
            xmlWriter.writeStartElement("Cme");
            xmlWriter.writeElementString("OrgReqDate", Format.Date8Format.format(p_req1998.getBgnDateTime()));
            xmlWriter.writeElementString("OrgReqSeqNo", p_req1998.reqBatchNO);
            xmlWriter.writeEndElement();
            xmlWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());// 发送银行
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpBkRespCode = tmpBkReader.getFirstText("/ap/RespCode");
                    String tmpBkRespInfo = tmpBkReader.getFirstText("/ap/RespInfo");
                    String tmpBkRespSource = tmpBkReader.getFirstText("/ap/RespSource");
                    String tmpBkOLBPRespCode = tmpBkReader.getFirstText("/ap/Cme/OLBPRespCode");
                    String tmpBkRxtInfo = tmpBkReader.getFirstText("/ap/RxtInfo");
                    String tmpATSRespInfo = tmpBkRespInfo;
                    if (tmpBkRxtInfo.isEmpty() == false) {
                        tmpATSRespInfo += "-" + tmpBkRxtInfo;
                    }
                    retAts.respInfo = tmpATSRespInfo;
                    if ("1015".equals(tmpBkRespCode)) {
                        retAts.respCode = "0";
                        retAts.respInfo = "单据不存在";
                        retAts.payInfoCode = tmpBkRespCode;
                        retAts.transState = tmpBkRespSource + "+" + tmpBkRespCode;
                        retAts.writeAfterDetail();
                        return retAts;
                    }
                    if ("0".equals(tmpBkRespSource)) {
						retAts.respCode = "0";
                        String tmpCheckStatus = tmpBkReader.getFirstText("/ap/Cme/CheckStatus").trim();
                        String tmpStrFileFlag = tmpBkReader.getFirstText("/ap/FileFlag");
                        // 1－发起后台批量记帐交易失败
                        // 2－发起后台批量记帐交易成功
                        // 3－下载后台记帐结果文件失败
                        // 4－下载后台记帐结果文件成功
                        if (("4").equals(tmpCheckStatus)) {
                            if ("1".equals(tmpStrFileFlag)) {
                                String tmpStrBatchFileName = tmpBkReader.getFirstText("/ap/Cmp/BatchFileName").trim();
                                if (tmpStrBatchFileName.length() > 0) {
                                    String tmpFilePath = "";
                                    String tmpQryRecFolder = bankFront.bkRecFolder;
                                    boolean isDirCut = getBankConfig().getValueAsBool("dirCutFlag");
                                    if (isDirCut) {
                                        tmpQryRecFolder = bankFront.bkQryRecFolder;
                                    }
                                    tmpFilePath = StringHelper.trimEnd(tmpQryRecFolder, File.separator) + File.separator + tmpStrBatchFileName;
                                    this.WriteBankLogLn("读取前置数据文件：" + tmpFilePath);
                                    String tmpResultData = "";
                                    if ("dspfileserver".equals(this.bankFront.getAccessBkFileModeLowerCase())) {
                                        WriteBankLogLn("accessBkFileMode：" + bankFront.accessBkFileMode);
                                        DspClient dspClient = new DspClient(bankFront.dspFileServer);
                                        dspClient.charsetName = getCharset();
                                        TcpReceiver tcpRec = dspClient.getFile(FileType.bankFile, tmpFilePath);
                                        if (tcpRec.isCompleted) {
                                            if (tcpRec.isRtnBinaryFile) {
                                                tmpResultData = new String(tcpRec.recBytes, tcpRec.contentStartIndex, tcpRec.contentLength, tcpRec.charsetName);
                                            } else {
                                                String errMsg = new String(tcpRec.recBytes, tcpRec.contentStartIndex, tcpRec.contentLength, tcpRec.charsetName);
                                                WriteBankLogLn("从远程DSP（" + bankFront.dspFileServer + "）获取前置文件未完成：" + errMsg);
                                            }
                                        } else {
                                            this.WriteBankLogLn("从远程DSP（" + bankFront.dspFileServer + "）获取前置文件未完成：" + tcpRec.getConnMsg());
                                        }
                                    }
                                    if ("ftp".equals(this.bankFront.getAccessBkFileModeLowerCase())) {
                                        FtpSet ftpSet = bankFront.getFtpSet("balCheck");
                                        String downFilePath = StringHelper.trimEndFileSp(ftpSet.downDir) + "/" + tmpStrBatchFileName;
                                        FtpPortClient ftpPtClient = new FtpPortClient(ftpSet);
                                        ftpPtClient.connect();
                                        FtpReceiver ftpReceiver = ftpPtClient.downloadFile(downFilePath, tmpFilePath);
                                        if (ftpReceiver.isCompleted) {
                                            WriteBankLogLn("成功下载结果文件:" + tmpStrBatchFileName + "至" + tmpFilePath);
                                        } else {
                                            WriteBankLogLn(tmpStrBatchFileName + "结果文件下载失败:" + ftpReceiver.connMsg + "+" + ftpReceiver.connState);
                                            retAts.respCode ="-1";
                                            retAts.respInfo = tmpStrBatchFileName + "结果文件下载失败:" + ftpReceiver.connMsg + "+" + ftpReceiver.connState;
                                            return retAts;
                                        }
                                        tmpResultData = FileHelper.readFileText(tmpFilePath, getCharset());
                                        WriteBankLogLn("结果文件内容为:" + tmpResultData);

                                    } else {
                                        tmpResultData = FileHelper.readFileText(tmpFilePath, getCharset());
                                    }
                                    WriteBankLogLn("银行查询文件返回内容为：" + tmpResultData);
                                    String[] tmpSeqIDArr = tmpResultData.split("\r\n");
                                    StringBuilder tmpSbLog = new StringBuilder();
                                    if (tmpSbLog.length() == 0) {
                                        retAts.respCode = "0";
                                        String totalNum = tmpSeqIDArr[0].substring(35, 41).trim();
                                        WriteBankLogLn("返回的总记录条数：" + Integer.parseInt(totalNum));
                                        String[] tmpSeqIDArrDetail = tmpSeqIDArr[1].split("\r");
                                        WriteBankLogLn("返回的明细数据：" + tmpSeqIDArr[1]);
                                        WriteBankLogLn("返回的明细数据数组：" + tmpSeqIDArrDetail.toString());
                                        WriteBankLogLn("返回的明细记录条数：" + (tmpSeqIDArrDetail.length));
                                        for (int i = 0; i < tmpSeqIDArrDetail.length; i++) {
                                            RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();
                                            byte[] tmpSeqId = tmpSeqIDArrDetail[i].getBytes(getCharset());
                                            byte[] tmpEachArr = new byte[tmpSeqId.length];
                                            System.arraycopy(tmpSeqId, 0, tmpEachArr, 0, tmpSeqId.length);
                                            String tmpStrCustPostScript = new String(tmpEachArr, 187, 246, "GBK").trim();
                                            String tmpStrCustResult = new String(tmpEachArr, 105, 4, "GBK").trim();

                                            String amount = StringHelper.amountDivide100(new String(tmpEachArr, 81, 13, "GBK").trim());
                                            tmpRetDetail.detailNo = new String(tmpEachArr, 14, 6, "GBK").trim();
                                            tmpRetDetail.payAmount = amount;
                                            tmpRetDetail.recName = new String(tmpEachArr, 21, 40, "GBK").trim();
                                            tmpRetDetail.recAct = new String(tmpEachArr, 61, 19, "GBK").trim();
                                            tmpRetDetail.curType = new String(tmpEachArr, 94, 3, "GBK").trim();
                                            tmpRetDetail.postScript = tmpStrCustPostScript;
                                            if ("0000".equals(tmpStrCustResult)) {
                                                tmpRetDetail.result = tmpCheckStatus + "-" + "2";
                                                tmpRetDetail.memo = "S0000-成功";
                                                tmpRetDetail.payInfoCode = tmpStrCustResult;
                                            } else {
                                                tmpRetDetail.result = tmpCheckStatus + "-" + "3";
                                                tmpRetDetail.memo = this.getBankConfig().getMapKeyByValue("PayInfoMapping", tmpStrCustResult);
                                                tmpRetDetail.payInfoCode = tmpStrCustResult;
                                            }
                                            retAts.writeRetDetail(tmpRetDetail);
                                        }
                                    } else {
                                        retAts.respCode = "-1";
                                        retAts.respInfo += "-读取文件失败,文件内容：" + tmpSbLog.toString();
                                    }
                                } else {
									retAts.respCode = "-1";
                                    retAts.respInfo = tmpATSRespInfo;
                                }
                            } else if ("0".equals(tmpStrFileFlag)) {
                                String tmpStrFieldNum = tmpBkReader.getFirstText("/ap/Cme/FieldNum").trim();
                                String tmpStrRecordNum = tmpBkReader.getFirstText("/ap/Cme/RecordNum").trim();
                                String tmpStrRxtInfo = tmpBkReader.getFirstText("/ap/RxtInfo").trim();
                                if (tmpStrFieldNum == "0" && tmpStrRecordNum == "0") {
                                    retAts.transState = tmpCheckStatus + "-" + "3";
                                    retAts.respInfo = "交易失败" + tmpStrRxtInfo;
                                }
                            }

                        } else if ("1".equals(tmpCheckStatus)) {
                            retAts.payInfoCode = tmpBkOLBPRespCode;
                            retAts.transState = tmpCheckStatus;
                            retAts.respInfo += "-发起后台批量记帐交易失败,请银行方重新提交批量记账申请";

                        } else if ("2".equals(tmpCheckStatus)) {
                            retAts.payInfoCode = tmpBkOLBPRespCode;
                            retAts.transState = tmpCheckStatus;
                            retAts.respInfo += "-发起后台批量记帐交易成功,但交易未必成功";

                        } else if ("3".equals(tmpCheckStatus)) {
                            retAts.payInfoCode = tmpBkOLBPRespCode;
                            retAts.transState = tmpCheckStatus;
                            retAts.respInfo += "-下载后台记帐结果文件失败,但交易未必成功";
                        }
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo += "-该次1972请求失败";
                    }
                } else {
					retAts.respCode = "-1";
                    retAts.respInfo = tmpStrRet[1];
                }
            }
        } catch (Exception e) {
			retAts.respCode = "-1";
			retAts.respInfo = e.getMessage();
            e.printStackTrace();
        }
        retAts.writeAfterDetail();
        return retAts;

    }

    @Override
    public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_req9188.reqHeader);
        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req9188.ownAct, "");
            if (actItem == null) {
                retAts.respCode = "-1";
                retAts.respInfo = "未找到账号[" + p_req9188.ownAct + "]商户配置信息";
                retAts.writeRetToATS();
                return retAts;
            }
            XmlTextWriter xmlWriter = new XmlTextWriter();
            ABC21Header bankHeader = new ABC21Header();
            bankHeader.transCode = "C602";
            bankHeader.reqSeqID = p_req9188.reqBatchNO;
            writeCommonHeader(xmlWriter, bankHeader);
            xmlWriter.writeElementString("SHAppCode", "SH04");
            xmlWriter.writeElementString("FileFlag", "1");
            xmlWriter.writeStartElement("Cmp");
            xmlWriter.writeElementClosed("BatchFileName");
            xmlWriter.writeEndElement();
            xmlWriter.writeEndDocument();

            StringBuilder tmpSbData = new StringBuilder();
            /** 第一行：汇总数据（记录长度500） */
            // 发起行号
            tmpSbData.append("0099999");
            // 代理业务种类
            tmpSbData.append("091");
            // 代理业务序号
            tmpSbData.append("0000");
            // 明细序号
            tmpSbData.append("000000");
            // 记账状态
            tmpSbData.append("0");
            // 资料检查状态
            tmpSbData.append("0");
            // 总金额
            tmpSbData.append(String.format("%013d", Long.parseLong(StringHelper.amountMultiply100(p_req9188.totalAmt))));
            // 总笔数
            tmpSbData.append(String.format("%06d", Integer.parseInt(p_req9188.totalNum)));
            // 成功记账总金额
            tmpSbData.append("0000000000000");
            // 成功记账总笔数
            tmpSbData.append("000000");
            // 代理单位名称
            String recName = fixedLenCompleSpace(40, p_req9188.ownActName, false);
            tmpSbData.append(recName);
            // 代理单位账号
            String recAct = fixedLenCompleSpace(20, p_req9188.ownAct, false);
            tmpSbData.append(recAct);
            // 申请入账日期
            tmpSbData.append(Format.Date8Format.format(p_req9188.getPayDateOnly()));
            // 上传日期
            tmpSbData.append(Format.Date8Format.format(p_req9188.getPayDateOnly()));
            // 剩余天数
            tmpSbData.append("000");
            // 企业代码
            tmpSbData.append(fixedLenCompleSpace(18, bankFront.org, false));
            // 业务类型
            tmpSbData.append(fixedLenCompleSpace(3, "", false));
            // 预留信息
            tmpSbData.append(fixedLenCompleSpace(340, "", false));
            tmpSbData.append("\r\n");

            /** 第二行及以下：明细数据（记录长度500） */
            // 发起行号
            StringBuilder tmpSbSeqIDData = new StringBuilder();
            int i = 0;
            while (p_req9188.readRecord()) {
                i++;
                tmpSbData.append("0099999");
                // 代理业务种类
                tmpSbData.append("091");
                // 代理业务序号
                tmpSbData.append("0000");
                // 明细序号
                tmpSbData.append(String.format("%06d", i));
                // 记账状态
                tmpSbData.append("0");
                // 付款方户名
                tmpSbData.append(fixedLenCompleSpace(40, p_req9188.readedDetail.payName, false));
                // 付款方账号
                String payAct = p_req9188.readedDetail.payAct;
                if (payAct.length() > 19) {
                   payAct = payAct.substring(0, 19);
                }
                payAct = fixedLenCompleSpace(19, payAct, false);
                tmpSbData.append(payAct);
                // 借贷标志
                tmpSbData.append("1");
                // 金额
                tmpSbData.append(String.format("%013d", Long.parseLong(StringHelper.amountMultiply100(p_req9188.readedDetail.payAmount))));
                // 币种
                String cur = convertCurToBank(p_req9188.readedDetail.payCur);
                tmpSbData.append(fixedLenCompleSpace(3, cur, false));
                // 传票号
                tmpSbData.append(fixedLenCompleSpace(8, "", false));
                // 记账错误码
                tmpSbData.append(fixedLenCompleSpace(4, "", false));
                // 记账日期
                tmpSbData.append("00000000");
                // 主机流水号
                tmpSbData.append("000000000");
                // 开户行
                tmpSbData.append("0000000");
                // 证件类型
                String certType = convertCertTypeToBank(p_req9188.readedDetail.certType);
                tmpSbData.append(fixedLenCompleSpace(6, certType, false));
                // 证件号码
                tmpSbData.append(fixedLenCompleSpace(40, p_req9188.readedDetail.certNum, false));
                // 摘要
                tmpSbData.append("00000000");
                // 备用
                tmpSbData.append(fixedLenCompleSpace(246, p_req9188.readedDetail.askNumber, false));
                // 二级账簿编号
                tmpSbData.append(fixedLenCompleSpace(10, "", false));
                // 备用
                tmpSbData.append(fixedLenCompleSpace(580, "", false));
                tmpSbData.append("\r\n");

                if (tmpSbSeqIDData.length() > 0) {
                    tmpSbSeqIDData.append("\r\n");
                }
                tmpSbSeqIDData.append(p_req9188.readedDetail.askNumber);
            }
            String tmpLocalMarkPath = getTempFileDirectory() + File.separator + p_req9188.reqBatchNO + ".txt";
            WriteBankLogLn2("批次明细序号映射文件路径: " + tmpLocalMarkPath);
            FileHelper.writeFile(tmpLocalMarkPath, tmpSbSeqIDData);
            String tmpFilePath = "";
            String tmpDataFileName = "C602_" + p_req9188.reqBatchNO + ".txt";
            if (StringHelper.isNullOrEmpty(bankFront.bkRecFolder)) {
                bankFront.bkRecFolder = bankFront.bkPayFolder;
            }
            tmpFilePath = StringHelper.trimEnd(bankFront.bkRecFolder, File.separator) + File.separator + tmpDataFileName;

            String cipherData = "";
            if ("dspfileserver".equals(this.bankFront.getAccessBkFileModeLowerCase())) {
                WriteBankLogLn("accessBkFileMode：" + bankFront.accessBkFileMode);
                DspClient dspClient = new DspClient(bankFront.dspFileServer);
                dspClient.charsetName = getCharset();
                TcpReceiver retReceiver = dspClient.putFile(isNeedHiddleField ? cipherData : tmpSbData.toString(), FileType.bankFile, tmpFilePath, false);
                if (retReceiver.isCompleted) {
                    String retXml = new String(retReceiver.recBytes, retReceiver.contentStartIndex, retReceiver.contentLength, retReceiver.charsetName);
                    XmlTextReader retXmlRd = new XmlTextReader(retXml);
                    if ("0".equals(retXmlRd.getSimpleText("RespCode"))) {
                        WriteBankLogLn("文件保存至前置机" + tmpFilePath + "成功");
                    } else {
                        WriteBankLogLn("文件保存至前置机" + tmpFilePath + "失败，响应报文：" + retXml);
                    }
                } else {
                    WriteBankLogLn("文件" + tmpFilePath + "保存失败：" + retReceiver.getConnMsg());
                    if (retReceiver.connState.equals(ConnState.FAIL)) {
                        WriteBankLogLn("连接主DSP服务" + bankFront.dspFileServer + "失败");
                    }
                }
            } else {
                WriteBankLogLn("请求代收付文件内容为:" + tmpSbData.toString());
                WriteBankLogLn("文件传送地址为:" + tmpFilePath);
                if (isNeedHiddleField) {

                    String bankPubKeyPath = getBankConfig().getValueAsString("BankPubKeyPath");
                    PublicKey publicKey = RsaHelper.decodePublicKeyFromFile(bankPubKeyPath);
                    // 对文件内容进行加密
                    byte[] encryptedDate = RsaHelper.encryptData(tmpSbData.toString().getBytes("gbk"), publicKey);
                    cipherData = new BASE64Encoder().encode(encryptedDate);
                    FileHelper.writeFile(tmpFilePath, cipherData, getCharset());
                } else {
                    FileHelper.writeFile(tmpFilePath, tmpSbData.toString(), getCharset());
                }
            }

            xmlWriter.writeEndDocument();// 写入报文完成
            String p_str = xmlWriter.toXmlString();
            p_str = p_str.replaceAll("<BatchFileName></BatchFileName>", "<BatchFileName>" + tmpDataFileName + "</BatchFileName>");
            String[] tmpStrRet = sendToBank(p_str);// 发送银行
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                // 解析银行返回
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRespCode = tmpBkReader.getFirstText("/ap/RespCode");
                    String tmpRetInfo = tmpBkReader.getFirstText("/ap/RespInfo");
                    String tmpRetRxtInfo = tmpBkReader.getFirstText("/ap/RxtInfo");
                    String tmpRespSource = tmpBkReader.getFirstText("/ap/RespSource");

                    // 当RxtInfo有内容返回，交易就会有异常
                    if (StringHelper.hasAnyChar(tmpRetRxtInfo)) {
                        retAts.respCode = "-1";
                        retAts.respInfo = tmpRetRxtInfo;
                    } else {
                        retAts.respCode = "0";
                        retAts.reqSeqID = p_req9188.reqBatchNO;
                        retAts.transState = tmpRespSource + "+" + tmpRespCode;
                        retAts.payInfoCode = tmpRespCode;
                        if ("0+0000".equals(retAts.transState)) {
                            retAts.respInfo = "提交处理成功，结果待查询！";
                        } else {
                            retAts.respInfo = tmpRetInfo;
                        }
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpSbMsg.toString();
                }
            } else if (tmpStrRet[0].equals(ConnState.FAIL)) {
                retAts.respCode = "0";
                retAts.respInfo = tmpStrRet[1];
                retAts.reqSeqID = p_req9188.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = tmpStrRet[0];
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = tmpStrRet[1];
            }

        } catch (Exception e) {
            retAts.respCode = "-1";
            retAts.respInfo = e.toString();
            WriteBankLogLn(e);
        }
        if (retAts.respCode.equals("-1") && StringHelper.isNullOrEmpty(retAts.reqSeqID)) {
            retAts.reqSeqID = p_req9188.reqBatchNO;
        }
        retAts.writeRetToATS();
        return retAts;
    }

    @Override
    public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_req9198.reqHeader);
        retAts.reqSeqID = p_req9198.reqBatchNO;
        try {
            XmlTextWriter xmlWriter = new XmlTextWriter();
            ABC21Header bankHeader = new ABC21Header();
            bankHeader.transCode = "C602";
            bankHeader.reqSeqID = p_req9198.reqBatchNO;
            writeCommonHeader(xmlWriter, bankHeader);
            xmlWriter.writeElementString("SHAppCode", "SH05");
            xmlWriter.writeStartElement("Cme");
            xmlWriter.writeElementString("OrgReqDate", Format.Date8Format.format(p_req9198.getBgnDateTime()));
            xmlWriter.writeElementString("OrgReqSeqNo", p_req9198.reqBatchNO);
            xmlWriter.writeEndElement();
            xmlWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());// 发送银行
            this.WriteBankLogLn("头部：" + tmpStrRet[0]);
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                this.WriteBankLogLn("明细：" + tmpStrRet[1]);
                if (tmpBkReader != null) {
                    String tmpBkRespCode = tmpBkReader.getFirstText("/ap/RespCode");
                    String tmpBkRespInfo = tmpBkReader.getFirstText("/ap/RespInfo");
                    String tmpBkRespSource = tmpBkReader.getFirstText("/ap/RespSource");
                    String tmpBkOLBPRespCode = tmpBkReader.getFirstText("/ap/Cme/OLBPRespCode");
                    String tmpBkRxtInfo = tmpBkReader.getFirstText("/ap/RxtInfo");
                    String tmpATSRespInfo = tmpBkRespInfo;
                    if (tmpBkRxtInfo.isEmpty() == false) {
                        tmpATSRespInfo += "-" + tmpBkRxtInfo;
                    }
                    retAts.respInfo = tmpATSRespInfo;
                    if ("1015".equals(tmpBkRespCode)) {
                        retAts.respCode = "0";
                        retAts.respInfo = "单据不存在";
                        retAts.payInfoCode = tmpBkRespCode;
                        retAts.transState = tmpBkRespSource + "+" + tmpBkRespCode;
                        retAts.writeAfterDetail();
                        return retAts;
                    }
                    if ("0".equals(tmpBkRespSource)) {
                        retAts.respCode = "0";
                        String tmpCheckStatus = tmpBkReader.getFirstText("/ap/Cme/CheckStatus").trim();
                        String tmpStrFileFlag = tmpBkReader.getFirstText("/ap/FileFlag");
                        String tmpReasonCode = tmpBkReader.getFirstText("/ap/ReasonCode");
                        // 1－发起后台批量记帐交易失败
                        // 2－发起后台批量记帐交易成功
                        // 3－下载后台记帐结果文件失败
                        // 4－下载后台记帐结果文件成功
                        if ("4".equals(tmpCheckStatus)) {
                            if ("1".equals(tmpStrFileFlag)) {
                                String tmpStrBatchFileName = tmpBkReader.getFirstText("/ap/Cmp/BatchFileName").trim();
                                if (tmpStrBatchFileName.length() > 0) {
                                    String tmpFilePath = "";
                                    String tmpQryRecFolder = bankFront.bkRecFolder;
                                    boolean isDirCut = getBankConfig().getValueAsBool("dirCutFlag");
                                    if (isDirCut) {
                                        tmpQryRecFolder = bankFront.bkQryRecFolder;
                                    }
                                    tmpFilePath = StringHelper.trimEnd(tmpQryRecFolder, File.separator) + File.separator + tmpStrBatchFileName;
                                    this.WriteBankLogLn("读取前置数据文件：" + tmpFilePath);
                                    String tmpResultData = "";
                                    if ("dspfileserver".equals(this.bankFront.getAccessBkFileModeLowerCase())) {
                                        WriteBankLogLn("accessBkFileMode：" + bankFront.accessBkFileMode);
                                        DspClient dspClient = new DspClient(bankFront.dspFileServer);
                                        dspClient.charsetName = getCharset();
                                        TcpReceiver tcpRec = dspClient.getFile(FileType.bankFile, tmpFilePath);
                                        if (tcpRec.isCompleted) {
                                            if (tcpRec.isRtnBinaryFile) {
                                                tmpResultData = new String(tcpRec.recBytes, tcpRec.contentStartIndex, tcpRec.contentLength, tcpRec.charsetName);
                                            } else {
                                                String errMsg = new String(tcpRec.recBytes, tcpRec.contentStartIndex, tcpRec.contentLength, tcpRec.charsetName);
                                                WriteBankLogLn("从远程DSP（" + bankFront.dspFileServer + "）获取前置文件未完成：" + errMsg);
                                            }
                                        } else {
                                            this.WriteBankLogLn("从远程DSP（" + bankFront.dspFileServer + "）获取前置文件未完成：" + tcpRec.getConnMsg());
                                        }
                                    }
                                    if ("ftp".equals(this.bankFront.getAccessBkFileModeLowerCase())) {
                                        FtpSet ftpSet = bankFront.getFtpSet("balCheck");
                                        String downFilePath = StringHelper.trimEndFileSp(ftpSet.downDir) + "/" + tmpStrBatchFileName;
                                        FtpPortClient ftpPtClient = new FtpPortClient(ftpSet);
                                        ftpPtClient.connect();
                                        FtpReceiver ftpReceiver = ftpPtClient.downloadFile(downFilePath, tmpFilePath);
                                        if (ftpReceiver.isCompleted) {
                                            WriteBankLogLn("成功下载结果文件:" + tmpStrBatchFileName + "至" + tmpFilePath);
                                        } else {
                                            WriteBankLogLn(tmpStrBatchFileName + "结果文件下载失败:" + ftpReceiver.connMsg + "+" + ftpReceiver.connState);
                                            retAts.respCode ="-1";
                                            retAts.respInfo = tmpStrBatchFileName + "结果文件下载失败:" + ftpReceiver.connMsg + "+" + ftpReceiver.connState;
                                            return retAts;
                                        }
                                        tmpResultData = FileHelper.readFileText(tmpFilePath, getCharset());
                                        WriteBankLogLn("结果文件内容为:" + tmpResultData);

                                    } else {
                                        tmpResultData = FileHelper.readFileText(tmpFilePath, getCharset());
                                    }
                                    WriteBankLogLn("银行查询文件返回内容为：" + tmpResultData);
                                    String[] tmpSeqIDArr = tmpResultData.split("\r\n");
                                    StringBuilder tmpSbLog = new StringBuilder();
                                    if (tmpSbLog.length() == 0) {
                                        retAts.respCode = "0";
                                        String totalNum = tmpSeqIDArr[0].substring(35, 41).trim();
                                        WriteBankLogLn("返回的总记录条数：" + Integer.parseInt(totalNum));
                                        String[] tmpSeqIDArrDetail = tmpSeqIDArr[1].split("\r");
                                        WriteBankLogLn("返回的明细数据：" + tmpSeqIDArr[1]);
                                        WriteBankLogLn("返回的明细数据数组：" + tmpSeqIDArrDetail.toString());
                                        WriteBankLogLn("返回的明细记录条数：" + (tmpSeqIDArrDetail.length));
                                        for (int i = 0; i < tmpSeqIDArrDetail.length; i++) {
                                            RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();
                                            byte[] tmpSeqId = tmpSeqIDArrDetail[i].getBytes(getCharset());
                                            byte[] tmpEachArr = new byte[tmpSeqId.length];
                                            System.arraycopy(tmpSeqId, 0, tmpEachArr, 0, tmpSeqId.length);
                                            String tmpStrCustPostScript = new String(tmpEachArr, 187, 246, "GBK").trim();
                                            String tmpStrCustResult = new String(tmpEachArr, 105, 4, "GBK").trim();

                                            String amount = StringHelper.amountDivide100(new String(tmpEachArr, 81, 13, "GBK").trim());
                                            tmpRetDetail.detailNo = new String(tmpEachArr, 14, 6, "GBK").trim();
                                            tmpRetDetail.payAmount = amount;
                                            tmpRetDetail.payName = new String(tmpEachArr, 21, 40, "GBK").trim();
                                            tmpRetDetail.payAct = new String(tmpEachArr, 61, 19, "GBK").trim();
                                            tmpRetDetail.curType = new String(tmpEachArr, 94, 3, "GBK").trim();
                                            tmpRetDetail.postScript = tmpStrCustPostScript;
                                            if ("0000".equals(tmpStrCustResult)) {
                                                tmpRetDetail.result = tmpCheckStatus + "-" + "2";
                                                tmpRetDetail.memo = "S0000-成功";
                                                tmpRetDetail.payInfoCode = tmpStrCustResult;
                                            } else {
                                                tmpRetDetail.result = tmpCheckStatus + "-" + "3";
                                                tmpRetDetail.memo = this.getBankConfig().getMapKeyByValue("PayInfoMapping", tmpStrCustResult);
                                                tmpRetDetail.payInfoCode = tmpStrCustResult;
                                            }
                                            retAts.writeRetDetail(tmpRetDetail);
                                        }
                                    } else {
                                        retAts.respCode ="-1";
                                        retAts.respInfo = tmpSbLog.toString();
                                    }
                                } else {
                                    retAts.respCode ="-1";
                                    retAts.respInfo = tmpATSRespInfo;
                                }
                            } else if ("0".equals(tmpStrFileFlag)) {
                                String tmpStrFieldNum = tmpBkReader.getFirstText("/ap/Cme/FieldNum").trim();
                                String tmpStrRecordNum = tmpBkReader.getFirstText("/ap/Cme/RecordNum").trim();
                                String tmpStrRxtInfo = tmpBkReader.getFirstText("/ap/RxtInfo").trim();
                                if (tmpStrFieldNum == "0" && tmpStrRecordNum == "0") {
                                    retAts.transState = tmpCheckStatus + "-" + "3";
                                    retAts.respInfo = "交易失败" + tmpStrRxtInfo;
                                }
                            }

                        } else if ("1".equals(tmpCheckStatus)) {
                            retAts.payInfoCode = tmpBkOLBPRespCode;
                            retAts.transState = tmpCheckStatus;
                            retAts.respInfo += "-发起后台批量记帐交易失败,请银行方重新提交批量记账申请";

                        } else if ("2".equals(tmpCheckStatus)) {
                            retAts.payInfoCode = tmpBkOLBPRespCode;
                            retAts.transState = tmpCheckStatus;
                            retAts.respInfo += "-发起后台批量记帐交易成功,但交易未必成功";

                        } else if ("3".equals(tmpCheckStatus)) {
                            retAts.payInfoCode = tmpBkOLBPRespCode;
                            retAts.transState = tmpCheckStatus;
                            retAts.respInfo += "-下载后台记帐结果文件失败,但交易未必成功";
                        }
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo += "-该次1972请求失败";
                    }
                } else {
                    retAts.respCode ="-1";
					retAts.respInfo = tmpStrRet[1];
                }
            }
        } catch (Exception e) {
            retAts.respCode ="-1";
			retAts.respInfo = e.getMessage();
            e.printStackTrace();
        }
        retAts.writeAfterDetail();
        return retAts;
    }
}
